﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace Futajma.MigrationStudio.DataDefinition.Dialog
{
    public partial class SearchAndReplaceCharacters : Form
    {

        GovernanceData _governanceData;
        private TextBox editbox = new TextBox();
        private TextBox editboxRegex = new TextBox();
        private ListViewHitTestInfo hitinfo;
        bool editCancled = false;
        bool editCancledRegexBox = false;
        TreeNode _targetTreeNode;


        public SearchAndReplaceCharacters(GovernanceData governanceData, TreeNode targetTreeNode)
        {
            _governanceData = governanceData;
            _targetTreeNode = targetTreeNode;

            InitializeComponent();
            editbox.Parent = lvSearchAndReplace;
            editbox.Hide();
            editbox.LostFocus += new EventHandler(editbox_LostFocus);
            editbox.KeyPress += editbox_KeyPress;

            editboxRegex.Parent = lvRegexPairs;
            editboxRegex.Hide();
            editboxRegex.LostFocus += new EventHandler(editboxRegex_LostFocus);
            editboxRegex.KeyPress += editboxRegex_KeyPress;
            

            lvSearchAndReplace.Columns.Add("Search", 50, HorizontalAlignment.Left);
            lvSearchAndReplace.Columns.Add("Replace with", 75, HorizontalAlignment.Left);

            lvRegexPairs.Columns.Add("Pattern", 50, HorizontalAlignment.Left);
            lvRegexPairs.Columns.Add("Replace with", 75, HorizontalAlignment.Left);
           
            btnTest.Enabled = false;

            cbxStringReplacements.Checked = false;
            cbxRegexPairs.Checked = false;
            cbxSearchandReplacePattern.Checked = false;

            // Load Governance Data
            LoadSettings();

        }

        

        private void editboxRegex_KeyPress(object sender, KeyPressEventArgs e)
        {
            switch ((Keys)e.KeyChar)
            {
                case Keys.Return:
                    editCancledRegexBox = false;
                    e.Handled = true;
                    editboxRegex.Hide();
                    break;
                case Keys.Escape:
                    editCancledRegexBox = true;
                    e.Handled = true;
                    editboxRegex.Hide();
                    break;
            }
        }

        private void editboxRegex_LostFocus(object sender, EventArgs e)
        {
            editboxRegex.Hide();

            if (editCancledRegexBox)
            {
                editCancledRegexBox = false;
            }
            else
            {
                hitinfo.SubItem.Text = editboxRegex.Text;
            }

            lvRegexPairs.Focus();
        }

        void editbox_KeyPress(object sender, KeyPressEventArgs e)
        {
            switch ((Keys)e.KeyChar)
            {
                case Keys.Return:
                    editCancled = false;
                    e.Handled = true;
                    editbox.Hide();
                    break;
                case Keys.Escape:
                    editCancled = true;
                    e.Handled = true;
                    editbox.Hide();
                    break;
            }
        }

        private void lvSearchAndReplace_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            var currentItem = lvSearchAndReplace.GetItemAt(e.X, e.Y);
            var currentSubItem = currentItem.GetSubItemAt(e.X, e.Y);
            var subItemIndex = currentItem.SubItems.IndexOf(currentSubItem);

            //if (subItemIndex)

            hitinfo = lvSearchAndReplace.HitTest(e.X, e.Y);
            editbox.Bounds = hitinfo.SubItem.Bounds;
            editbox.Text = hitinfo.SubItem.Text;
            editbox.Focus();
            editbox.Show();
        }

        void editbox_LostFocus(object sender, EventArgs e)
        {
            editbox.Hide();

            if (editCancled)
            {
                editCancled = false;
            }
            else
            {
                hitinfo.SubItem.Text = editbox.Text;
            }

            lvSearchAndReplace.Focus();
        }

        private void LoadSettings()
        {
            foreach (var item in _governanceData.SearchAndReplaceCharacters)
            {
                ListViewItem lwItem = new ListViewItem(new[] { item.SearchCharacter, item.ReplaceCharacter });
                //lwItem.Tag = item.Id;
                lvSearchAndReplace.Items.Add(lwItem);
            }
            foreach (var item in _governanceData.ReplaceRegularExpressionPairs)
            {
                ListViewItem lwItem = new ListViewItem(new[] { item.SearchCharacter, item.ReplaceCharacter });
                //lwItem.Tag = item.Id;
                lvRegexPairs.Items.Add(lwItem);
            }
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            ListViewItem lwItem = new ListViewItem(new[] { "", "" });
            //lwItem.Tag = item.Id;
            var newItem = lvSearchAndReplace.Items.Add(lwItem);
            lvSearchAndReplace.SelectedItems.Clear();
            newItem.Selected = true;
            newItem.EnsureVisible();
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem eachItem in lvSearchAndReplace.SelectedItems)
            {
                lvSearchAndReplace.Items.Remove(eachItem);
            }
        }

        private void lvSearchAndReplace_KeyDown(object sender, KeyEventArgs e)
        {
            if (lvSearchAndReplace.SelectedItems.Count != 0)
            {
                if (e.KeyCode == Keys.F2)
                {
                    e.Handled = true;
                    BeginEditListItem(lvSearchAndReplace.SelectedItems[0], 1);
                }
            }
        }

        private void BeginEditListItem(ListViewItem listViewItem, int subItemIndex)
        {
            var pt = listViewItem.SubItems[subItemIndex].Bounds.Location;

            var evArg = new MouseEventArgs(MouseButtons.Left, 2, pt.X, pt.Y, 0);
            lvSearchAndReplace_MouseDoubleClick(listViewItem.ListView, evArg);
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            _governanceData.SearchAndReplaceCharacters.Clear();

            foreach (ListViewItem item in lvSearchAndReplace.Items)
            {
                if (item.Text.Length > 0)
                {
                    _governanceData.SearchAndReplaceCharacters.Add(new SearchReplacePair() { SearchCharacter = item.Text, ReplaceCharacter = item.SubItems[1].Text });
                }
            }
        }

        void SetProgressStatus(bool inProgress)
        {
            Cursor.Current = inProgress ? Cursors.WaitCursor : Cursors.Default;
            cbxFilename.Enabled = !inProgress;
            cbxFoldername.Enabled = !inProgress;
            btnAdd.Enabled = !inProgress;
            btnCancel.Enabled = !inProgress;
            btnSave.Enabled = !inProgress;
            btnSimulation.Enabled = !inProgress;
            btnExecution.Enabled = !inProgress;
        }

        private void btnSimulation_Click(object sender, EventArgs e)
        {
            ExecutionReplacement(true);
        }

        private void btnExecution_Click(object sender, EventArgs e)
        {
            ExecutionReplacement(false);
        }

        private void ExecutionReplacement(bool simulation)
        {
            try
            {
                SaveFileDialog dlg = new SaveFileDialog();
                dlg.RestoreDirectory = true;
                dlg.Filter = "Report|*.xml";
                dlg.Title = "Save search and replace report.";

                if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    _targetTreeNode.TreeView.BeginUpdate();

                    SetProgressStatus(true);

                    var output = new List<SearchReplaceResult>();

                    if (cbxFilename.Checked)
                    {
                        if (cbxStringReplacements.Enabled && lvSearchAndReplace.Items.Count > 0)
                        {
                            _governanceData.SearchReplaceUnsupportedCharacters(_targetTreeNode, output, SharePointType.Document, simulation);
                            _governanceData.SearchReplaceUnsupportedCharacters(_targetTreeNode, output, SharePointType.Item, simulation);
                        }

                        if (cbxRegexPairs.Checked && lvRegexPairs.Items.Count > 0)
                        {
                            _governanceData.SearchReplaceRegularExpression(_targetTreeNode, output, SharePointType.Document, simulation);
                            _governanceData.SearchReplaceRegularExpression(_targetTreeNode, output, SharePointType.Item, simulation);
                        }

                        if (cbxSearchandReplacePattern.Checked && txtPattern.Text.Length > 0 && txtReplacement.Text.Length > 0)
                        {
                            _governanceData.SearchReplaceRegularExpression(_targetTreeNode, output, SharePointType.Document, txtPattern.Text, txtReplacement.Text, simulation);
                            _governanceData.SearchReplaceRegularExpression(_targetTreeNode, output, SharePointType.Item, txtPattern.Text, txtReplacement.Text, simulation);
                        }
                    }
                    if (cbxFoldername.Checked)
                    {
                        if (cbxStringReplacements.Enabled && lvSearchAndReplace.Items.Count > 0)
                        {
                            _governanceData.SearchReplaceUnsupportedCharacters(_targetTreeNode, output, SharePointType.Folder, simulation);
                        }

                        if (cbxRegexPairs.Checked && lvRegexPairs.Items.Count > 0)
                        {
                            _governanceData.SearchReplaceRegularExpression(_targetTreeNode, output, SharePointType.Folder, simulation);
                        }

                        if (cbxSearchandReplacePattern.Checked && txtPattern.Text.Length > 0 && txtReplacement.Text.Length > 0)
                        {
                            _governanceData.SearchReplaceRegularExpression(_targetTreeNode, output, SharePointType.Folder, txtPattern.Text, txtReplacement.Text, simulation);
                        }
                    }

                    _governanceData.SaveSearchReplaceUnsupportedCharacterReport(dlg.FileName, output);

                    Cursor.Current = Cursors.Default;

                    MessageBox.Show(string.Format("Report saved,  {0} folders or filenames replaces", output.Count), simulation ? "Information: only try run!" : "Information");
                }
            }
            catch (ArgumentException ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                _targetTreeNode.TreeView.EndUpdate();
                SetProgressStatus(false);
            }
        }

        //private void cbxRegularExpression_CheckedChanged(object sender, EventArgs e)
        //{
        //    gbxRegularExpression.Enabled = cbxRegularExpression.Checked;
        //}

        private void btnTest_Click(object sender, EventArgs e)
        {
            try
            {
                string newTitle = txtTestString.Text;
                // test search and replace list
                if (cbxSearchandReplacePattern.Enabled && lvSearchAndReplace.Items.Count > 0)
                {
                    var test = new StringBuilder(newTitle);
                    _governanceData.SearchAndReplaceCharacters.ForEach(sp => test = test.Replace(sp.SearchCharacter, sp.ReplaceCharacter));
                    newTitle = test.ToString();
                }

                // test regex pairs list
                if (cbxRegexPairs.Enabled && lvRegexPairs.Items.Count > 0)
                {
                    _governanceData.ReplaceRegularExpressionPairs.ForEach(sp => newTitle = Regex.Replace(newTitle, sp.SearchCharacter, sp.ReplaceCharacter));
                }


                // test manual regex
                if (txtReplacement.Text.Length > 0 && txtPattern.Text.Length > 0)
                {
                    //var test = new StringBuilder(newTitle);
                    //SearchAndReplaceCharacters.ForEach(sp => test = test.Replace(sp.SearchCharacter, sp.ReplaceCharacter));
                    newTitle = Regex.Replace(newTitle, txtPattern.Text, txtReplacement.Text);
                }

                txtOutput.Text = newTitle;
               
               
                
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void txtPattern_TextChanged(object sender, EventArgs e)
        {
            TestTextState();
        }

        private void txtReplacement_TextChanged(object sender, EventArgs e)
        {
            TestTextState();
        }

        private void txtTestString_TextChanged(object sender, EventArgs e)
        {
            TestTextState();
        }

        private void txtOutput_TextChanged(object sender, EventArgs e)
        {
            TestTextState();
        }

        private void TestTextState()
        {
            if (txtTestString.Text.Length > 0)
            {
                btnTest.Enabled = true;
            }
            else
            {
                btnTest.Enabled = false;
            }
        }

        #region RegexPair ListView
        private void lvRegexPairs_KeyDown(object sender, KeyEventArgs e)
        {
            if (lvRegexPairs.SelectedItems.Count != 0)
            {
                if (e.KeyCode == Keys.F2)
                {
                    e.Handled = true;
                    BeginEditListItemRegexPair(lvRegexPairs.SelectedItems[0], 1);
                }
            }
        }

        private void BeginEditListItemRegexPair(ListViewItem listViewItem, int subItemIndex)
        {
            var pt = listViewItem.SubItems[subItemIndex].Bounds.Location;

            var evArg = new MouseEventArgs(MouseButtons.Left, 2, pt.X, pt.Y, 0);
            lvRegexPairs_MouseDoubleClick(listViewItem.ListView, evArg);
        }

        private void lvRegexPairs_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            var currentItem = lvRegexPairs.GetItemAt(e.X, e.Y);
            var currentSubItem = currentItem.GetSubItemAt(e.X, e.Y);
            var subItemIndex = currentItem.SubItems.IndexOf(currentSubItem);

            //if (subItemIndex)

            hitinfo = lvRegexPairs.HitTest(e.X, e.Y);
            editboxRegex.Bounds = hitinfo.SubItem.Bounds;
            editboxRegex.Text = hitinfo.SubItem.Text;
            editboxRegex.Focus();
            editboxRegex.Show();
        }

        private void btnAddRegex_Click(object sender, EventArgs e)
        {
            ListViewItem lwItem = new ListViewItem(new[] { "", "" });
            //lwItem.Tag = item.Id;
            var newItem = lvRegexPairs.Items.Add(lwItem);
            lvRegexPairs.SelectedItems.Clear();
            newItem.Selected = true;
            newItem.EnsureVisible();
        }

        private void btnDeleteRegexPair_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem eachItem in lvRegexPairs.SelectedItems)
            {
                lvRegexPairs.Items.Remove(eachItem);
            }
        }

        private void btnSaveRegexPairs_Click(object sender, EventArgs e)
        {
            _governanceData.ReplaceRegularExpressionPairs.Clear();

            foreach (ListViewItem item in lvRegexPairs.Items)
            {
                if (item.Text.Length > 0)
                {
                    _governanceData.ReplaceRegularExpressionPairs.Add(new SearchReplacePair() { SearchCharacter = item.Text, ReplaceCharacter = item.SubItems[1].Text });
                }
            }
        }
        #endregion

        private void cbx_EnabledChanged(object sender, EventArgs e)
        {
            UpdateButton();
        }

        private void UpdateButton()
        {
            gbxTest.Enabled = btnSimulation.Enabled = btnExecution.Enabled = cbxStringReplacements.Checked || cbxRegexPairs.Checked || cbxSearchandReplacePattern.Checked;
        }
       
    }
}
